package com.bridata.real;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;

@Slf4j
public class RealDataHandleOptimized {
    private static final int MAX_RETRIES = 3;
    private static final int HTTP_TIMEOUT = 5000; // 5秒
    // 线程池配置
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
    private static final ExecutorService processExecutor = Executors.newFixedThreadPool(Runtime
        .getRuntime()
        .availableProcessors() * 2);
    // 性能监控指标
    private static final AtomicLong successCount = new AtomicLong(0);
    private static final AtomicLong failureCount = new AtomicLong(0);
    private static DruidDataSource dataSource;
    private static Integer batchSize = 2;

    public static void main(String[] args) {
        try {
            initDataSource();
            startScheduledTasks();
            addShutdownHook();
        } catch (Exception e) {
            System.out.println("系统初始化失败");
            System.exit(1);
        }
    }

    private static void initDataSource() {
        try {
            dataSource = new DruidDataSource();
            dataSource.setUrl(
                "jdbc:mysql://10.120.79.139:3306/dts_external_data?useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
            dataSource.setUsername("root");
            dataSource.setPassword("bjbn123");
            dataSource.setInitialSize(5);
            dataSource.setMinIdle(5);
            dataSource.setMaxActive(20);
            dataSource.setMaxWait(60000);
            dataSource.setTestWhileIdle(true);
            dataSource.setValidationQuery("SELECT 1");
            System.out.println("数据库连接池初始化成功");
        } catch (Exception e) {
            System.out.println("系统初始化失败");
            System.out.println(e);
            throw new RuntimeException(e);
        }
    }

    private static void startScheduledTasks() {
        // 主定时任务
        scheduler.scheduleAtFixedRate(RealDataHandleOptimized::processMainTask, 0, 1, TimeUnit.SECONDS);
        // 监控统计任务
        scheduler.scheduleAtFixedRate(() -> log.info("处理统计 - 成功: {}, 失败: {}",
            successCount.get(),
            failureCount.get()
        ), 1, 1, TimeUnit.MINUTES);
    }

    private static Integer index = -1;

    private static void processMainTask() {
        try {
            index = index + 1;
            System.out.println("当前请求位置：" + index);
            try (Connection conn = dataSource.getConnection()) {
                List<ScreenPicture> records = fetchRecords(conn, index, batchSize);
                if (records.isEmpty()) {
                    System.out.println("未找到待处理记录");
                    index = -1;
                    return;
                }
                processRecordsAsync(records);
            }
        } catch (Exception e) {
            System.out.println("主任务执行失败:" + e);
        }
    }

    private static List<ScreenPicture> fetchRecords(Connection conn, int currentSecond, int size) throws SQLException {
        int offset = currentSecond * size;
        System.out.println("当前请求数据起始：" + offset + ", 查询条数：" + size);
        String sql = "SELECT id, template_id FROM t_fids_screen_picture ORDER BY id LIMIT ?, ?";
        List<ScreenPicture> records = new ArrayList<>();
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setInt(1, offset);
            ps.setInt(2, size);
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                records.add(ScreenPicture
                    .builder()
                    .id(rs.getInt("id"))
                    .template_id(rs.getString("template_id"))
                    .build());
            }
        }
        return records;
    }

    private static void processRecordsAsync(List<ScreenPicture> records) {
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        for (ScreenPicture record : records) {
            futures.add(CompletableFuture.runAsync(() -> {
                try {
                    processSingleRecord(record);
                    successCount.incrementAndGet();
                } catch (Exception e) {
                    failureCount.incrementAndGet();
                    System.out.println("记录处理失败 ID: " + record.getId());
                }
            }, processExecutor));
        }
        try {
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get(30, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            log.warn("任务执行超时，已处理 {} 条记录", successCount.get());
        } catch (Exception e) {
            log.error("批量任务执行异常", e);
        }
    }

    private static void processSingleRecord(ScreenPicture record) {
        if (StringUtils.isEmpty(record.getTemplate_id())) {
            return;
        }
        String imageData = fetchImageWithRetry(record);
        updateDatabaseRecord(record, imageData);
    }

    private static String fetchImageWithRetry(ScreenPicture record) {
        for (int retry = 0; retry < MAX_RETRIES; retry++) {
            try {
                return fetchImageData(record);
            } catch (Exception e) {
                if (retry == MAX_RETRIES - 1) {
                    throw new RuntimeException("API请求失败", e);
                }
                sleepExponentialBackoff(retry);
            }
        }
        return "";
    }

    private static String fetchImageData(ScreenPicture item) {
        System.out.println("当前请求数据id: " + item.getTemplate_id());
        String baseUrl = "http://10.120.79.139:3000/api/url2image";
        String picUrl = String.format("http://10.128.103.90:8098/t2fids-web-boss/template/templates/view.do?id=%s",
            item.getTemplate_id()
        );
        JSONObject requestBody = new JSONObject();
        // {"url":"http://10.128.103.90:8098/t2fids-web-boss/template/templates/view.do?id=de8a4dd5cd6a43c6974b6d1dc9d2b619","width":"1920","height":"1080","fullPage":false,"autoSize":false,"imageFormat":"jpeg","imageQuality":"60"}
        requestBody.put("url", picUrl);
        requestBody.put("width", "1920");
        requestBody.put("height", "1080");
        requestBody.put("fullPage", false);
        requestBody.put("autoSize", false);
        requestBody.put("imageFormat", "jpeg");
        requestBody.put("imageQuality", "60");
        HttpResponse response = HttpRequest
            .post(baseUrl)
            .body(requestBody.toJSONString())
            .timeout(HTTP_TIMEOUT)
            .execute();
        if (response.getStatus() != 200) {
            System.out.println("HTTP请求失败，状态码: " + response.getStatus());
        }
        JSONObject responseJson = JSONObject.parseObject(response.body());
        return responseJson.getString("imageBase64WithPrefix");
    }

    private static void updateDatabaseRecord(ScreenPicture record, String imageData) {
        try (Connection conn = dataSource.getConnection()) {
            String sql = "UPDATE t_fids_screen_picture SET update_time = now(), picture = ? WHERE id = ?";
            try (PreparedStatement ps = conn.prepareStatement(sql)) {
                ps.setString(1, imageData);
                ps.setInt(2, record.getId());
                int affectedRows = ps.executeUpdate();
                if (affectedRows == 0) {
                    System.out.println("未更新任何记录 ID: " + record.getId());
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("数据库更新失败", e);
        }
    }

    private static void sleepExponentialBackoff(int retryCount) {
        try {
            Thread.sleep(1000L * (1 << retryCount));
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }
    }

    private static void addShutdownHook() {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("系统关闭中...");
            shutdownGracefully();
        }));
    }

    private static void shutdownGracefully() {
        try {
            scheduler.shutdown();
            processExecutor.shutdown();
            if (!scheduler.awaitTermination(10, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
            if (!processExecutor.awaitTermination(10, TimeUnit.SECONDS)) {
                processExecutor.shutdownNow();
            }
            dataSource.close();
            System.out.println("资源释放完成");
        } catch (Exception e) {
            System.out.println("关闭过程中发生异常: " + e);
        }
    }
}